<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xalan="http://xml.apache.org/xalan" version="1.0">
  <xsl:output method="xml" indent="yes"/>
  <xsl:template match="/"><!-- NOTE: match root of XML Doc -->
    <xsl:element name="ROWSET"><!-- NOTE: Create ROWSET Element for output -->
      <xsl:apply-templates select="//NODE[LEVEL_ = '1']" mode="group"><!-- NOTE: apply-templates to just to only the NODE elements have a value 0f '1' for the LEVEL_ attribute and use the mode attribute set to group -->
        <xsl:sort select="LEVEL_"/><!-- NOTE: Sort by the LEVEL_ element to ensure we get the results in the proper order.  OBVIOUSLY this particular case doesnt require us to sort them given that we are only matching to "LEVEL_" values of 1 in our XPath statement.  But, for the sake of good practice (if the criteria every changes then the sorting is already in place) I put it in there. -->
        <xsl:with-param name="allElements" select="*"/><!-- NOTE: pass the parameter all element, seleceting all the elements in the XML Doc -->
      </xsl:apply-templates>
    </xsl:element>
  </xsl:template>
  <xsl:template match="NODE" mode="group"><!-- NOTE: this template matches all "NODE" elements that were called from apply-templates that used the mode attribute of "group" -->
    <xsl:param name="allElements"/><!-- NOTE: create parameter that will be set to the value passed by the template -->
    <xsl:variable name="SRCD" select="SRCD"/><!-- NOTE: create SCRD variable for each NODE element that passes through this template.  This will be used to compare to the first character of all the other NODE elements for grouping -->
    <xsl:variable name="groups"><!-- NOTE: create a variable named group that holds the Result Tree Fragment of the grouping process -->
      <xsl:element name="group"><!-- NOTE: create element "group" that will the hold the contents of each distinct group that is passed from the origination template -->
        <xsl:apply-templates select="$allElements/NODE[starts-with(SRCD, $SRCD)]" mode="groupTree"><!-- NOTE: apply-templates using the allElements parameter passed from the previous template.  This parameter contains and RTF of all the elements and attributes in the XML Doc.  The processor will look for the first element in the RTF created by the XPath in the select attribute and match it to the first template that contains the proper element in the match attribute and the mode attribute set to "groupTree" -->
          <xsl:sort select="LEVEL_"/><!-- NOTE: sort using the "LEVEL_" value element -->
          <xsl:sort select="translate(SRCD, ',', '')"/><!-- NOTE:  then sort on the translated value of the SRCD element (this removes the commas so the processor can sort them as standard integers.  This isnt always necessary but its good practice to ensure accurate results EVERY time -->
        </xsl:apply-templates>
      </xsl:element>
    </xsl:variable>
    <xsl:apply-templates select="xalan:nodeset($groups)" mode="groupTreeBranches"/><!-- NOTE:  use the nodeset function of your particular processor (dont forget to declare the namespace extension in your xsl:stylesheet decleration to convert the RTF created by the above apply-templates process -->
  </xsl:template>
  <xsl:template match="NODE" mode="groupTree"><!-- NOTE:  the above template matches each NODE elements that matched the grouping criteria created in the above templates.  In this case it took each NODE that had a "LEVEL_" element value of '1'.  The next template matched the first character in the "SRCD" element of every node with the 4 elements that matched the previous templates rules.  So in this case the first template that matched -->
    <xsl:element name="NODE"><!-- NOTE:  It the creates a NODE element in the output stream -->
      <xsl:copy-of select="child::*"/><!-- NOTE:  and then copys all the elements contained within the originating NODE in the output stream as well -->
    </xsl:element><!-- once this process has completed (all 4 original matching elements are grouped properly with there respective elements) the second apply-templates will be called, parsing through the RTF created by this process matching (to the specified XPath) each element contained within the direct document flow (meaning the sibling elements that were matched with the XPath statement).  To access any elements contained within these sibling elements will require another apply-templates call from the next template (if recursive behavior is required.  Given that the XML Doc file started as a flat file doesnt allow for a simple example of the recursive nature of apply-templates but the process has at least given us four distinct groups to work with now which will allow some recursion processing to make our job easier. -->
  </xsl:template>
  <xsl:template match="group" mode="groupTreeBranches"><!-- NOTE:  the template before this one created a nodeset from a RTF from the prior process and has now began matching its elements to this template -->
    <xsl:apply-templates select="NODE[LEVEL_ = 1]" mode="groupTreeBranches"/><!-- NOTE: this template simply takes, once again, our "NODE" elements that have a "LEVEL_" value of 1.  This will allow us to then use recursion to access the remaining elements in the group and reunite them with there long lost parent and potential siblings -->
  </xsl:template>
  <xsl:template match="NODE" mode="groupTreeBranches"><!-- NOTE:  the above template matches to this template (again, using match and mode to ensure we are accessing the template intended for this particular pass through the NODE elements-->
    <xsl:variable name="LEVEL_" select="LEVEL_"/><!-- NOTE:  a "LEVEL_" variable is created to be used for comparisons in our parent/child grouping process about to take place -->
    <xsl:variable name="SRCD" select="SRCD" /><!-- NOTE:  again, another comparison variable is created, this time the value of the "SCRD" element is set to the variable name "SCRD" (this doesnt create any problems in our XPath because we access variables using the $ sign in front telling our processor to access the variable value and not the element value -->
    <xsl:element name="NODE"><!-- NOTE:  again, another NODE element is created.  However this one will be a permanent fixture in our final output where as our previous NODE element was created as a temporary, yet structured, place holder of the values we want to access is this processing of the final output -->
      <xsl:element name="SRCD"><!-- NOTE:  a "SRCD" element is created in our output tree and the value set to the value of the current NODE element in context -->
        <xsl:value-of select="SRCD"/><!-- NOTE:  value is set using xsl:value-of to access the content found between the opening and closing SRCD tags -->
      </xsl:element>
      <xsl:copy-of select="child::*[contains(name(), 'ELEMENT')]"/><!-- this process makes a copy of all child elements of our context node (in this case literally NODE) that match the XPath test that using the contains function and uses the name() function as the test to see if it contains the sequence of characters "ELEMENT". If yes, it makes a copy of the entire element and associated values to the output.  If no, it continues testing each child element until there are no more to test.  Please note that this particular XPath test didnt include any reference to text() or comment() (which are technically text() nodes) nodes and as such any contained within the child structure of the containing NODE element would not be tested by the processor.  -->
      <xsl:element name="CHILDREN"><!-- NOTE:  heres where we create our CHILDREN element and the use XPath tests and recursion to process the remaining NODE elements and place them with there proper parent and respective siblings -->
        <xsl:apply-templates select="following-sibling::NODE[LEVEL_ = $LEVEL_ + 1 and substring(SRCD, 1, string-length($SRCD)) = $SRCD]" mode="groupTreeBranches"/><!-- NOTE:  this apply-templates uses "following-sibling" as its axis for testing whether or not the next node is a child of any prior NODE elements.  Two tests are performed and both must pass for this element to become a child or sibling element to the current NODE element in process.  The first adds a value of "1" to the "LEVEL_" variable we created earlier in the process and then tests to see if the value of this NODEs "LEVEL_" element is equal.  If it is then we know that this is a potential candidate as a child node.  But were not done yet.  Our XPath statement used the following-sibling axis with no designation to position so our processor is checking EVERY following sibling to see if its "LEVEL_" value is = the "LEVEL_" variable + 1.  Given that it is very likely that somewhere along the way a "LEVEL_" element contained in a following NODE element will have a distance of levels deep within the document that is the same as the "LEVEL_" variable + 1 then this test alone will not be adequate.  Our next test uses the string-length of the "SRCD" element of the first preceding-sibling NODE element whos "LEVEL_" value is exactly one less than that of the NODE in question and then uses that to trim the length of the current CDFS element and then compares the two.  If this preceding-element is truly the parent of this element in question then their "genetic" sequence should match.  For example, if the previous matching element had a value of 3,1 for SRCD then for our element to be a child he/she too would have to have 3,1 as his/her first two values.  If he/she does, WHAMO, a family had bee reunited.  If not, the quest (at least for this NODE element) to find his long lost family members must continue during the next pass through yet one more temporary foster home-->
      </xsl:element><!-- NOTE: every match made using the XPath test above will be processed within the context of this "CHILDREN" element.  Given that we use the same match element ("NODE") and the same mode ("groupTreeBranches") as the xsl:template it is contained in then each matching node will also go through this quest to find there long lost children.  As such this template has created a recursive process that will continue without hesitation or concern for anything but bringing back together each familys mom, dad, father, son, mother, daugther, sister, brother, grandm.... ok, ill stop ;) -->
    </xsl:element>
  </xsl:template>
</xsl:stylesheet>
